#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   BOOT_RequestDownload_0x34_test.py
@Time    :   2025/04/08 10:35:23
@Author  :   Yang Liang
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''

# here put the import lib
import shutil
import zipfile
from pytest_assume.plugin import assume

import pytest
import time
from commDriver.TS_CAN import *
import allure
import sys
from collections.abc import Iterable
import Set_up
from tests.download.DownLoad import Download
from commDriver.parseFile import *
sys.dont_write_bytecode = True

RequestDownload_NRC13 = [
    ("34", "7F 34 13"),
    ("34 00", "7F 34 13"),
    ("34 00 44", "7F 34 13"),
    ("34 00 44 00", "7F 34 13"),
    ("34 00 44 00 05 00 00 00 00 00", "7F 34 13"),
    ("34 01 44 00 05 00 00 00 00 00 01 01", "7F 34 13"),
    ("34 00 44 05 00 00 00 00 00 00 01 01", "7F 34 13"),
    ("34 10 44 00 03 00 00 00 00 00", "7F 34 13")
]
RequestDownload_NRC31 = [ 
    ('34 00 44 00 05 00 00 FF FF FF FF','7F 34 31'),
    ('34 00 44 00 7A 00 00 FF FF FF FF','7F 34 31'),  
    ('34 00 44 00 02 00 00 FF FF FF FF','7F 34 31'), 
    ('34 00 44 00 02 A0 00 FF FF FF FF','7F 34 31'), 
    ('34 00 44 FF FF FF FF 00 09 7F 22','7F 34 31'), 
    ('34 00 44 FF FF FF FF FF FF FF FF','7F 34 31'),
    ('34 00 55 00 05 00 00 00 09 7F 22','7F 34 31'), 
    ('34 11 44 00 05 00 00 00 09 7F 22','7F 34 31'),
    ('34 10 44 00 05 00 00 00 09 7F 22','7F 34 31'),
    ('34 01 44 00 05 00 00 00 09 7F 22','7F 34 31'), 
    ('34 00 66 00 05 00 00 00 09 7F 22','7F 34 31'),            
]  


flashDriverPath = Set_up.flashDriverPath
App_path = Set_up.soft_path


class Test_BOOT_RequestDownload_Phy(object):

    parse_File = ParseFile()

    ids = [f"Request {req}" for req,resp in RequestDownload_NRC13]
    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-0x34-测试NRC13')
    @allure.description('测试物理寻址编程会话下34服务的NRC13')
    @pytest.mark.parametrize('req,resp',RequestDownload_NRC13,ids = ids)
    def test_RequestDownload_NRC13_Programming_Phy(self,action,Driver,req,resp):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, True)

    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-0x34-测试NRC33')
    @allure.description('测试物理寻址编程会话下34服务的NRC33')
    def test_RequestDownload_NRC33_Programming_Phy(self,Driver,action):
        iStep = 1 
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '34 00 44 00 7A 00 00 00 00 28 0A', '7F 34 33', 2, iStep, False)

    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-0x34-无flashDriver刷写APP响应NRC70')
    @allure.description('测试物理寻址编程会话下34服务无flashDriver刷写APP的NRC70')
    def test_RequestDownload_NRC70_APP_NoFlashDriver_Phy(self,Driver,action):
        iStep = 1
        start_address_APP,segment_size_APP  = self.GetAppAdressAndLength()
        Request_download_CMD = self.construct_request_command([0x34, 0x00, 0x44], start_address_APP, segment_size_APP) 
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, Request_download_CMD, '7F 34 70', 2, iStep, True)

    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-0x34-未擦除刷写APP响应NRC70')
    @allure.description('测试物理寻址编程会话下34服务未擦除刷写APP的NRC70')
    def test_RequestDownload_NRC70_APP_Phy(self, Driver, action):
        iStep = 1
        dl = Download(Driver['CAN'], Driver['UDS'], Driver['UDSFun'], Set_up.flashDriverPath, Set_up.soft_path, 
                     onlyFlashDrv=True)
        dl.join()
        start_address_APP, segment_size_APP = self.GetAppAdressAndLength()
        Request_download_CMD = self.construct_request_command([0x34, 0x00, 0x44], start_address_APP, segment_size_APP)
        iStep, uds_resp, size = Driver['CAN'].checkReqResp(Driver, Request_download_CMD, '7F 34 70', 0, iStep, False)


    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-34服务NRC13 NRC31优先级')
    @allure.description('验证物理寻址编程会话下34服务NRC13 NRC31优先级')
    def test_RequestDownload_NRC13andNRC31_Priority_Programming_Phy(self, action, Driver):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, "34 88 01", "7F 34 13", 2, iStep, True)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, "34 66 77 88", "7F 34 13", 0, iStep, False)

    @allure.severity('normal')
    @allure.title('物理寻址-编程会话-34服务NRC31 NRC13优先级')
    @allure.description('验证物理寻址编程会话下34服务NRC31 NRC13优先级')
    def test_RequestDownload_NRC31andNRC13_Priority_Programming_Phy(self, action, Driver):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, "34 88 01 02 03 04 05 06", "7F 34 31", 2, iStep, True)
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, "34 66 01 02 03 04 05", "7F 34 31", 0, iStep, False)


    # @allure.severity('minor')
    # @allure.description('Test NRC12 of 0x34 in programming session in bootloader with physical addressing')
    # @allure.testcase('Test cases address:https://chengtech.pingcode.com/testhub/libraries/62a69d6cb35db4f20e37703a/cases')
    # def test_RequestDownload_NRC12_Phy(self,Driver,action):
    #      iStep = 1
    #      iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, [0x34,0x81,0x44,0x01,0x7A,0x00,0x00,0x00,0x00,0x28,0x0A], [0x7F,0x34,0x12], 2, iStep, True)


    @allure.severity('minor')
    @allure.title('物理寻址-扩展会话-0x34-测试NRC11')
    @allure.description('测试物理寻址扩展会话下34服务的NRC11')
    def test_RequestDownload_NRC11_Phy(self,Driver,action):
          iStep = 1
          iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, '34 00 44 00 7A 00 00 00 00 28 0A]', '7F 34 11', 3, iStep, True)

    ids = [f"Request {req}" for req,resp in RequestDownload_NRC31]
    @allure.severity('minor')
    @allure.title('物理寻址-编程会话-0x34-测试NRC31')
    @allure.description('测试物理寻址编程会话下34服务的NRC31')
    @pytest.mark.parametrize('req,resp',RequestDownload_NRC31,ids = ids)
    def test_RequestDownload_NRC31_Phy(self,action,Driver,req,resp):
        iStep = 1
        iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, req, resp, 2, iStep, True)

    # @allure.severity('minor')
    # @allure.description('Test NRC31 of 0x34 in programming session in bootloader with physical addressing')
    # @allure.testcase('Test cases address:https://chengtech.pingcode.com/testhub/libraries/62a69d6cb35db4f20e37703a/cases')
    # def test_RequestDownload_NRC31_Phy(self,Driver,action):
    #      iStep = 1
    #      start_address,segment_size = self.GetAppAdressAndLength()
    #      #长度不对
    #      Request_download_CMD = [0x34,00,0x44] + \
    #                               [(start_address>>24) & 0xFF] + [(start_address>>16) & 0xFF] + [(start_address>>8) & 0xFF] + [(start_address) & 0xFF] +\
    #                               [0xFF] + [0xFF] + [0xFF] + [0xFF]
    #      iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, Request_download_CMD, [0x7F,0x34,0x31], 2, iStep, True)

    #      #地址不对
    #      Request_download_CMD = [0x34,00,0x44] + \
    #                               [0xFF] + [0xFF] + [0xFF] + [0xFF] +\
    #                               [(segment_size>>24) & 0xFF] + [(segment_size>>16) & 0xFF] + [(segment_size>>8) & 0xFF] + [(segment_size) & 0xFF]
    #      iStep,uds_resp, size = Driver['CAN'].checkReqResp(Driver, Request_download_CMD, [0x7F,0x34,0x31], 0, iStep)

    def construct_request_command(self, base_cmd, address, size):
        """
        构造请求下载命令字节流
        :param base_cmd: 基础命令字节列表（如[0x34, 0x00, 0x44]），表示服务ID及子功能
        :param address: 目标地址（32位无符号整数），大端格式存储
        :param size: 数据大小（32位无符号整数），大端格式存储
        :return: 完整的请求命令字节列表（包含基础命令+地址+数据大小）
        """
        return base_cmd + [
            (address >> 24) & 0xFF, (address >> 16) & 0xFF,  # 地址高位到低位
            (address >> 8) & 0xFF, address & 0xFF, 
            (size >> 24) & 0xFF, (size >> 16) & 0xFF,      # 大小高位到低位
            (size >> 8) & 0xFF, size & 0xFF
        ]

    def GetAppAdressAndLength(self):
        # 获取APP 应用程序地址和长度
        startaddress, size = self.parse_File.get_Address_Lenth(App_path)
        logging.info('startaddress: {}, size: {}'.format(startaddress,size))
        # 处理多地址段：计算最小起始地址和总擦除大小
        segment_size_APP = max(size)         # 计算所有地址段的总长度
        for i in range(len(size)):
            if size[i] == max(size):
                start_address_APP = startaddress[i]
                break
        # try:
        #     tempPath = os.path.abspath(os.path.join(os.getcwd(),"./tests/0x34/temp"))
        #     shutil.rmtree(tempPath)
        #     tempPath = os.path.abspath(os.path.join(os.getcwd(),"./tests/download/temp"))
        #     shutil.rmtree(tempPath)
        # except Exception as e:
        #     logging.error(f"删除临时目录时发生错误: {e}")
        #     pass

        return start_address_APP, segment_size_APP